package com.java.kettle;


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

public class Encr {
    public static final String KETTLE_PASSWORD_ENCODER_PLUGINS_FILE = "KETTLE_PASSWORD_ENCODER_PLUGINS_FILE";
    public static final String KETTLE_PASSWORD_ENCODER_PLUGIN = "KETTLE_PASSWORD_ENCODER_PLUGIN";
    public static final String KETTLE_TWO_WAY_PASSWORD_ENCODER_SEED = "KETTLE_TWO_WAY_PASSWORD_ENCODER_SEED";
    public static final String XML_FILE_KETTLE_PASSWORD_ENCODER_PLUGINS = "kettle-password-encoder-plugins.xml";
    private static final String FILE_SEPARATOR = System.getProperty("file.separator");
    protected static boolean isJunitTest;
    protected static int exitCode;
    public static final String PASSWORD_ENCRYPTED_PREFIX = "Encrypted ";
    protected static Encr instance;
    private Map<String, TwoWayPasswordEncoderInterface> encoderMap = new HashMap();
    private String defaultEncoderId;
    private String firstId;

    private Encr() {
    }

    public static Encr getInstance() throws PasswordEncoderException, XmlParseException {
        if (instance == null) {
            Encr encr = new Encr();
            encr.setupPasswordEncoders();
            instance = encr;
        }

        return instance;
    }

    public String encryptPassword(String password) {
        return this.encryptPassword(this.getDefaultEncoderId(), password);
    }

    public String encryptPassword(String encoderId, String password) {
        return this.getEncoder(encoderId).encode(password, false);
    }

    public String decryptPassword(String password) {
        return this.decryptPassword(this.getDefaultEncoderId(), password);
    }

    public String decryptPassword(String encoderId, String encrypted) {
        return this.getEncoder(encoderId).decode(encrypted);
    }

    public String encryptPasswordIfNotUsingVariables(String password) {
        return this.encryptPasswordIfNotUsingVariables(this.getDefaultEncoderId(), password);
    }

    public String encryptPasswordIfNotUsingVariables(String encoderId, String password) {
        return this.getEncoder(encoderId).encode(password, true);
    }

    public String decryptPasswordOptionallyEncrypted(String password) {
        return this.decryptPasswordOptionallyEncrypted(this.getDefaultEncoderId(), password);
    }

    public String decryptPasswordOptionallyEncrypted(String encoderId, String password) {
        return this.getEncoder(encoderId).decode(password, true);
    }

    private void setupPasswordEncoders() throws PasswordEncoderException {
        String xmlFile = "kettle-password-encoder-plugins.xml";
        String alternative = StringUtil.NVL(System.getProperty("KETTLE_PASSWORD_ENCODER_PLUGINS_FILE"), (String)null);

        boolean registeredDefault;
        try {
            registeredDefault = this.registerPlugins(xmlFile);
        } catch (Exception e) {
            throw new PasswordEncoderException("Unable to load native plugins '" + xmlFile + "'", e);
        }

        boolean registeredAlternative;
        try {
            registeredAlternative = this.registerPlugins(alternative);
        } catch (Exception e) {
            throw new PasswordEncoderException("Unable to load alternative plugins '" + alternative + "'", e);
        }

        if (!registeredDefault && !registeredAlternative) {
            throw new PasswordEncoderException("Unable to load a defining plugin xml file for TwoWayPasswordEncoderInteface.  Please create file 'kettle-password-encoder-plugins.xml'");
        }
    }

    private boolean registerPlugins(String xmlFile) throws PasswordEncoderException, XmlParseException {
        if (!StringUtil.isEmpty(xmlFile)) {
            InputStream inputStream = this.getResAsStreamExternal(xmlFile);
            if (inputStream == null) {
                inputStream = this.getResAsStreamExternal("/" + xmlFile);
            }

            if (inputStream != null) {
                this.registerPlugins(inputStream);
                if (this.defaultEncoderId == null) {
                    this.defaultEncoderId = this.firstId;
                }

                return true;
            }
        }

        return false;
    }

    private void registerPlugins(InputStream inputStream) throws PasswordEncoderException, XmlParseException {
        try {
            Document document = XMLHandler.loadXMLFile(inputStream, false);
            Node repsNode = XMLHandler.getSubNode(document, "password-encoder-plugins");

            for(Node repNode : XMLHandler.getNodes(repsNode, "password-encoder-plugin")) {
                this.registerPluginFromXmlResource(repNode);
            }
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException var12) {
            }

        }

    }

    protected void registerPluginFromXmlResource(Node pluginNode) throws PasswordEncoderException {
        String idTag = XMLHandler.getTagAttribute(pluginNode, "id");
        String classname = this.getTagOrAttribute(pluginNode, "classname");
        String defaultTag = this.getTagOrAttribute(pluginNode, "default-encoder");
        String seedXML = this.getTagOrAttribute(pluginNode, "seed");
        if (seedXML != null) {
            System.setProperty("KETTLE_TWO_WAY_PASSWORD_ENCODER_SEED", seedXML);
        }

        boolean isDefault = defaultTag != null && (defaultTag.toLowerCase().startsWith("t") || defaultTag.toLowerCase().startsWith("y"));

        try {
            Class clazz = Class.forName(classname);
            TwoWayPasswordEncoderInterface encoder = (TwoWayPasswordEncoderInterface)clazz.newInstance();
            encoder.init();
            String id = idTag.toLowerCase();
            this.encoderMap.put(id, encoder);
            if (isDefault) {
                if (this.defaultEncoderId != null) {
                    throw new PasswordEncoderException("Only one encoder can be marked as \"default-encoder\"");
                }

                this.defaultEncoderId = id;
            }

            if (this.firstId == null) {
                this.firstId = id;
            }

        } catch (ClassNotFoundException var10) {
            throw new PasswordEncoderException("ClassNotFound: " + classname);
        } catch (IllegalAccessException | InstantiationException var11) {
            throw new PasswordEncoderException("Could not instantiate: " + classname);
        }
    }

    private String getTagOrAttribute(Node pluginNode, String tag) {
        String string = XMLHandler.getTagValue(pluginNode, tag);
        if (string == null) {
            string = XMLHandler.getTagAttribute(pluginNode, tag);
        }

        return string;
    }

    private InputStream getResAsStreamExternal(String name) {
        return this.getClass().getResourceAsStream(name);
    }

    private InputStream getFileInputStreamExternal(String name) throws FileNotFoundException {
        return new FileInputStream(name);
    }

    private TwoWayPasswordEncoderInterface getEncoder(String encoderId) {
        TwoWayPasswordEncoderInterface encoder = (TwoWayPasswordEncoderInterface)instance.encoderMap.get(encoderId);
        if (encoder == null) {
            throw new RuntimeException("plugin id '" + encoderId + "' does not exist");
        } else {
            return encoder;
        }
    }

    private String getDefaultEncoderId() {
        return StringUtil.NVL(System.getProperty("KETTLE_PASSWORD_ENCODER_PLUGIN"), this.defaultEncoderId).toLowerCase();
    }

    private static void printOptions() {
        System.err.println("encr usage:\n");
        System.err.println("  encr <-kettle|-carte> <password>");
        System.err.println("  Options:");
        System.err.println("    -kettle: generate an obfuscated password to include in Kettle XML files");
        System.err.println("    -carte : generate an obfuscated password to include in the carte password file 'pwd/kettle.pwd'");
        System.err.println("\nThis command line tool obfuscates a plain text password for use in XML and password files.");
        System.err.println("Make sure to also copy the 'Encrypted ' prefix to indicate the obfuscated nature of the password.");
        System.err.println("Kettle will then be able to make the distinction between regular plain text passwords and obfuscated ones.");
        System.err.println();
    }

    private static boolean exitIfNotTest(int exitCode) {
        if (isJunitTest) {
            Encr.exitCode = exitCode;
        } else {
            System.exit(exitCode);
        }

        return true;
    }
}
